return texture;
}
-void
-_st_theme_node_paint_state_free (StThemeNodePaintState *state)
-{
- int corner_id;
-
- if (state->background_texture != COGL_INVALID_HANDLE)
- cogl_handle_unref (state->background_texture);
- if (state->background_material != COGL_INVALID_HANDLE)
- cogl_handle_unref (state->background_material);
- if (state->background_shadow_material != COGL_INVALID_HANDLE)
- cogl_handle_unref (state->background_shadow_material);
- if (state->border_slices_texture != COGL_INVALID_HANDLE)
- cogl_handle_unref (state->border_slices_texture);
- if (state->border_slices_material != COGL_INVALID_HANDLE)
- cogl_handle_unref (state->border_slices_material);
- if (state->prerendered_texture != COGL_INVALID_HANDLE)
- cogl_handle_unref (state->prerendered_texture);
- if (state->prerendered_material != COGL_INVALID_HANDLE)
- cogl_handle_unref (state->prerendered_material);
- if (state->box_shadow_material != COGL_INVALID_HANDLE)
- cogl_handle_unref (state->box_shadow_material);
-
- for (corner_id = 0; corner_id < 4; corner_id++)
- if (state->corner_material[corner_id] != COGL_INVALID_HANDLE)
- cogl_handle_unref (state->corner_material[corner_id]);
-
- _st_theme_node_paint_state_init (state);
-}
-
-void
-_st_theme_node_paint_state_init (StThemeNodePaintState *state)
-{
- int corner_id;
-
- state->background_texture = COGL_INVALID_HANDLE;
- state->background_material = COGL_INVALID_HANDLE;
- state->background_shadow_material = COGL_INVALID_HANDLE;
- state->box_shadow_material = COGL_INVALID_HANDLE;
- state->border_slices_texture = COGL_INVALID_HANDLE;
- state->border_slices_material = COGL_INVALID_HANDLE;
- state->prerendered_texture = COGL_INVALID_HANDLE;
- state->prerendered_material = COGL_INVALID_HANDLE;
-
- for (corner_id = 0; corner_id < 4; corner_id++)
- state->corner_material[corner_id] = COGL_INVALID_HANDLE;
-}
-
static void st_theme_node_paint_borders (StThemeNode *node,
StThemeNodePaintState *state,
const ClutterActorBox *box,
* geometry change versus things that can be cached regardless, such as
* a background image.
*/
- _st_theme_node_paint_state_free (state);
+ st_theme_node_paint_state_free (state);
state->alloc_width = width;
state->alloc_height = height;
void
st_theme_node_paint (StThemeNode *node,
+ StThemeNodePaintState *state,
const ClutterActorBox *box,
guint8 paint_opacity)
{
float width, height;
ClutterActorBox allocation;
- StThemeNodePaintState *state = &node->state;
/* Some things take an ActorBox, some things just width/height */
width = box->x2 - box->x1;
}
}
-static void
+void
+st_theme_node_paint_state_free (StThemeNodePaintState *state)
+{
+ int corner_id;
+
+ if (state->background_texture != COGL_INVALID_HANDLE)
+ cogl_handle_unref (state->background_texture);
+ if (state->background_material != COGL_INVALID_HANDLE)
+ cogl_handle_unref (state->background_material);
+ if (state->background_shadow_material != COGL_INVALID_HANDLE)
+ cogl_handle_unref (state->background_shadow_material);
+ if (state->border_slices_texture != COGL_INVALID_HANDLE)
+ cogl_handle_unref (state->border_slices_texture);
+ if (state->border_slices_material != COGL_INVALID_HANDLE)
+ cogl_handle_unref (state->border_slices_material);
+ if (state->prerendered_texture != COGL_INVALID_HANDLE)
+ cogl_handle_unref (state->prerendered_texture);
+ if (state->prerendered_material != COGL_INVALID_HANDLE)
+ cogl_handle_unref (state->prerendered_material);
+ if (state->box_shadow_material != COGL_INVALID_HANDLE)
+ cogl_handle_unref (state->box_shadow_material);
+
+ for (corner_id = 0; corner_id < 4; corner_id++)
+ if (state->corner_material[corner_id] != COGL_INVALID_HANDLE)
+ cogl_handle_unref (state->corner_material[corner_id]);
+
+ st_theme_node_paint_state_init (state);
+}
+
+void
+st_theme_node_paint_state_init (StThemeNodePaintState *state)
+{
+ int corner_id;
+
+ state->background_texture = COGL_INVALID_HANDLE;
+ state->background_material = COGL_INVALID_HANDLE;
+ state->background_shadow_material = COGL_INVALID_HANDLE;
+ state->box_shadow_material = COGL_INVALID_HANDLE;
+ state->border_slices_texture = COGL_INVALID_HANDLE;
+ state->border_slices_material = COGL_INVALID_HANDLE;
+ state->prerendered_texture = COGL_INVALID_HANDLE;
+ state->prerendered_material = COGL_INVALID_HANDLE;
+
+ for (corner_id = 0; corner_id < 4; corner_id++)
+ state->corner_material[corner_id] = COGL_INVALID_HANDLE;
+}
+
+void
st_theme_node_paint_state_copy (StThemeNodePaintState *state,
StThemeNodePaintState *other)
{
if (state == other)
return;
- /* Check omitted for speed: */
- /* g_return_if_fail (st_theme_node_paint_equal (node, other)); */
-
- _st_theme_node_paint_state_free (state);
+ st_theme_node_paint_state_free (state);
state->alloc_width = other->alloc_width;
state->alloc_height = other->alloc_height;
state->corner_material[corner_id] = cogl_handle_ref (other->corner_material[corner_id]);
}
-/**
- * st_theme_node_copy_cached_paint_state:
- * @node: a #StThemeNode
- * @other: a different #StThemeNode
- *
- * Copy cached painting state from @other to @node. This function can be used to
- * optimize redrawing cached background images when the style on an element changess
- * in a way that doesn't affect background drawing. This function must only be called
- * if st_theme_node_paint_equal (node, other) returns %TRUE.
- */
void
-st_theme_node_copy_cached_paint_state (StThemeNode *node,
- StThemeNode *other)
-{
- st_theme_node_paint_state_copy (&node->state,
- &other->state);
-}
-
-static void
st_theme_node_paint_state_invalidate (StThemeNodePaintState *state)
{
state->alloc_width = 0;
state->alloc_height = 0;
}
-
-void
-st_theme_node_invalidate_paint_state (StThemeNode *node)
-{
- st_theme_node_paint_state_invalidate (&node->state);
-}
G_BEGIN_DECLS
-typedef struct _StThemeNodePaintState StThemeNodePaintState;
-
-struct _StThemeNodePaintState {
- float alloc_width;
- float alloc_height;
-
- CoglHandle background_texture;
- CoglHandle background_material;
- CoglHandle border_slices_texture;
- CoglHandle border_slices_material;
- CoglHandle background_shadow_material;
- CoglHandle box_shadow_material;
- CoglHandle prerendered_texture;
- CoglHandle prerendered_material;
- CoglHandle corner_material[4];
-};
-
struct _StThemeNode {
GObject parent;
guint background_image_shadow_computed : 1;
guint text_shadow_computed : 1;
guint link_type : 2;
-
- StThemeNodePaintState state;
};
struct _StThemeNodeClass {
void _st_theme_node_ensure_background (StThemeNode *node);
void _st_theme_node_ensure_geometry (StThemeNode *node);
-void _st_theme_node_paint_state_init (StThemeNodePaintState *state);
-void _st_theme_node_paint_state_free (StThemeNodePaintState *state);
-
G_END_DECLS
#endif /* __ST_THEME_NODE_PRIVATE_H__ */
StThemeNode *old_theme_node;
StThemeNode *new_theme_node;
+ StThemeNodePaintState old_paint_state;
+ StThemeNodePaintState new_paint_state;
+
CoglHandle old_texture;
CoglHandle new_texture;
StThemeNodeTransition *
st_theme_node_transition_new (StThemeNode *from_node,
StThemeNode *to_node,
+ StThemeNodePaintState *old_paint_state,
guint duration)
{
StThemeNodeTransition *transition;
transition->priv->old_theme_node = g_object_ref (from_node);
transition->priv->new_theme_node = g_object_ref (to_node);
+ st_theme_node_paint_state_copy (&transition->priv->old_paint_state,
+ old_paint_state);
+
transition->priv->timeline = clutter_timeline_new (duration);
transition->priv->timeline_completed_id =
return transition;
}
+StThemeNodePaintState *
+st_theme_node_transition_get_new_paint_state (StThemeNodeTransition *transition)
+{
+ return &transition->priv->new_paint_state;
+}
+
void
st_theme_node_transition_update (StThemeNodeTransition *transition,
StThemeNode *new_node)
*/
if (st_theme_node_equal (new_node, old_node))
{
+ {
+ StThemeNodePaintState tmp = priv->old_paint_state;
+ priv->old_paint_state = priv->new_paint_state;
+ priv->new_paint_state = tmp;
+ }
+
if (clutter_timeline_get_elapsed_time (priv->timeline) > 0)
{
if (direction == CLUTTER_TIMELINE_FORWARD)
clutter_timeline_set_duration (priv->timeline, new_duration);
- /* If the change doesn't affect painting, we don't need to redraw,
- * but we still need to replace the node so that we properly share
- * caching with the painting that happens after the transition finishes.
- */
- if (!st_theme_node_paint_equal (priv->new_theme_node, new_node))
- priv->needs_setup = TRUE;
-
g_object_unref (priv->new_theme_node);
priv->new_theme_node = g_object_ref (new_node);
+
+ st_theme_node_paint_state_invalidate (&priv->new_paint_state);
}
}
}
cogl_ortho (priv->offscreen_box.x1, priv->offscreen_box.x2,
priv->offscreen_box.y2, priv->offscreen_box.y1,
0.0, 1.0);
- st_theme_node_paint (priv->old_theme_node, allocation, 255);
+ st_theme_node_paint (priv->old_theme_node, &priv->old_paint_state, allocation, 255);
cogl_pop_framebuffer ();
cogl_push_framebuffer (priv->new_offscreen);
cogl_ortho (priv->offscreen_box.x1, priv->offscreen_box.x2,
priv->offscreen_box.y2, priv->offscreen_box.y1,
0.0, 1.0);
- st_theme_node_paint (priv->new_theme_node, allocation, 255);
+ st_theme_node_paint (priv->new_theme_node, &priv->new_paint_state, allocation, 255);
cogl_pop_framebuffer ();
return TRUE;
priv->timeline_completed_id = 0;
priv->timeline_new_frame_id = 0;
+ st_theme_node_paint_state_free (&priv->old_paint_state);
+ st_theme_node_paint_state_free (&priv->new_paint_state);
+
G_OBJECT_CLASS (st_theme_node_transition_parent_class)->dispose (object);
}
transition->priv->old_offscreen = NULL;
transition->priv->new_offscreen = NULL;
+ st_theme_node_paint_state_init (&transition->priv->old_paint_state);
+ st_theme_node_paint_state_init (&transition->priv->new_paint_state);
+
transition->priv->needs_setup = TRUE;
}
StThemeNodeTransition *st_theme_node_transition_new (StThemeNode *from_node,
StThemeNode *to_node,
+ StThemeNodePaintState *old_paint_state,
guint duration);
void st_theme_node_transition_update (StThemeNodeTransition *transition,
const ClutterActorBox *allocation,
ClutterActorBox *paint_box);
+StThemeNodePaintState * st_theme_node_transition_get_new_paint_state (StThemeNodeTransition *transition);
+
G_END_DECLS
#endif
st_theme_node_init (StThemeNode *node)
{
node->transition_duration = -1;
- _st_theme_node_paint_state_init (&node->state);
}
static void
if (node->background_image)
g_free (node->background_image);
- _st_theme_node_paint_state_free (&node->state);
-
G_OBJECT_CLASS (st_theme_node_parent_class)->finalize (object);
}
ST_GRADIENT_RADIAL
} StGradientType;
+typedef struct _StThemeNodePaintState StThemeNodePaintState;
+
+struct _StThemeNodePaintState {
+ float alloc_width;
+ float alloc_height;
+
+ CoglHandle background_texture;
+ CoglHandle background_material;
+ CoglHandle border_slices_texture;
+ CoglHandle border_slices_material;
+ CoglHandle background_shadow_material;
+ CoglHandle box_shadow_material;
+ CoglHandle prerendered_texture;
+ CoglHandle prerendered_material;
+ CoglHandle corner_material[4];
+};
+
GType st_theme_node_get_type (void) G_GNUC_CONST;
StThemeNode *st_theme_node_new (StThemeContext *context,
StThemeNode *other);
void st_theme_node_paint (StThemeNode *node,
+ StThemeNodePaintState *state,
const ClutterActorBox *box,
guint8 paint_opacity);
-void st_theme_node_copy_cached_paint_state (StThemeNode *node,
- StThemeNode *other);
-void st_theme_node_invalidate_paint_state (StThemeNode *node);
+void st_theme_node_paint_state_init (StThemeNodePaintState *state);
+void st_theme_node_paint_state_free (StThemeNodePaintState *state);
+void st_theme_node_paint_state_copy (StThemeNodePaintState *state,
+ StThemeNodePaintState *other);
+void st_theme_node_paint_state_invalidate (StThemeNodePaintState *node);
G_END_DECLS
* that we can remove the pseudo classes on them. */
StWidget *prev_last_child;
StWidget *prev_first_child;
+
+ StThemeNodePaintState paint_state;
};
/**
if (!changed)
return;
- st_theme_node_invalidate_paint_state (node);
+ st_theme_node_paint_state_invalidate (&actor->priv->paint_state);
if (CLUTTER_ACTOR_IS_MAPPED (CLUTTER_ACTOR (actor)))
clutter_actor_queue_redraw (CLUTTER_ACTOR (actor));
g_free (priv->accessible_name);
g_free (priv->inline_style);
+ st_theme_node_paint_state_free (&priv->paint_state);
+
G_OBJECT_CLASS (st_widget_parent_class)->finalize (gobject);
}
&allocation,
opacity);
else
- st_theme_node_paint (theme_node, &allocation, opacity);
+ st_theme_node_paint (theme_node,
+ &widget->priv->paint_state,
+ &allocation,
+ opacity);
}
static void
g_signal_connect (actor, "notify::last-child", G_CALLBACK (st_widget_last_child_notify), NULL);
g_signal_connect (st_texture_cache_get_default (), "texture-file-changed",
G_CALLBACK (st_widget_texture_cache_changed), actor);
+
+ st_theme_node_paint_state_init (&priv->paint_state);
}
static void
on_transition_completed (StThemeNodeTransition *transition,
StWidget *widget)
{
+ st_theme_node_paint_state_copy (&widget->priv->paint_state,
+ st_theme_node_transition_get_new_paint_state (transition));
+
st_widget_remove_transition (widget);
}
paint_equal = old_theme_node && st_theme_node_paint_equal (old_theme_node, new_theme_node);
- if (paint_equal)
- st_theme_node_copy_cached_paint_state (new_theme_node, old_theme_node);
-
g_object_get (gtk_settings_get_default (),
"gtk-enable-animations", &animations_enabled,
NULL);
widget->priv->transition_animation =
st_theme_node_transition_new (old_theme_node,
new_theme_node,
+ &widget->priv->paint_state,
transition_duration);
g_signal_connect (widget->priv->transition_animation, "completed",
st_widget_remove_transition (widget);
}
+ if (!paint_equal)
+ st_theme_node_paint_state_invalidate (&widget->priv->paint_state);
+
g_signal_emit (widget, signals[STYLE_CHANGED], 0);
widget->priv->is_style_dirty = FALSE;
}